//
// Created by yunnan xu on 2020/11/25.
//

#include "Model.h"
#include "EngineCore.h"
#include "Texture.h"
#include <gles3/gl32.h>
#include "ResourceMgr.h"
#include "glm.hpp"
#include "gtx/transform.hpp"
#include "RigidBody.h"

Model::Model()
{
    translation_mat = glm::mat4(1.0f);
    rotate_mat = glm::mat4(1.0f);
    scale_mat = glm::mat4(1.0f);
    transform = glm::mat4(1.0f);
}

Model::~Model()
{
    rb = nullptr;
}

const glm::mat4 & Model::GetModelMatrix() const
{
    return transform;
}

void Model::SetModelMatrix(glm::mat4 mat)
{
    transform = mat;
}

void Model::SetTranslation(glm::vec3 translation, bool sync_to_rb)
{
    translation_mat = glm::mat4(1.0f);
    translation_mat[3][0] = translation.x;
    translation_mat[3][1] = translation.y;
    translation_mat[3][2] = translation.z;
    transform = translation_mat * rotate_mat * scale_mat;

    if (rb && sync_to_rb)
    {
        rb->SetTranslationMat(translation_mat);
        rb->convex->UpdateWithModelMatrix(transform);
    }
}


void Model::SetRotation(glm::vec3 rotation, bool sync_to_rb)
{
    rotate_mat = glm::mat4(1.0f);
    rotate_mat *= glm::rotate(rotation.x, glm::vec3(1, 0, 0));
    rotate_mat *= glm::rotate(rotation.y, glm::vec3(0, 1, 0));
    rotate_mat *= glm::rotate(rotation.z, glm::vec3(0, 0, 1));
    transform = translation_mat * rotate_mat * scale_mat;

    if (rb && sync_to_rb)
    {
        rb->SetRotateMat(rotate_mat);
        rb->convex->UpdateWithModelMatrix(transform);
    }

}


void Model::SetScale(glm::vec3 scale, bool sync_to_rb)
{
    scale_mat = glm::mat4(1.0f);
    scale_mat[0][0] = scale[0];
    scale_mat[1][1] = scale[1];
    scale_mat[2][2] = scale[2];
    transform = translation_mat * rotate_mat * scale_mat;

    if (rb && sync_to_rb)
    {
        rb->SetScaleMat(scale_mat);
        rb->convex->UpdateWithModelMatrix(transform);
    }

}

void Model::SetTranslation(glm::mat4 mat, bool sync_to_rb)
{
    translation_mat = mat;
    transform = translation_mat * rotate_mat * scale_mat;

    if (rb && sync_to_rb)
    {
        rb->SetTranslationMat(mat);
        rb->convex->UpdateWithModelMatrix(transform);
    }
}

void Model::SetRotation(glm::mat4 mat, bool sync_to_rb)
{
    rotate_mat = mat;
    transform = translation_mat * rotate_mat * scale_mat;

    if (rb && sync_to_rb)
    {
        rb->SetRotateMat(mat);
        rb->convex->UpdateWithModelMatrix(transform);
    }
}

void Model::SetScale(glm::mat4 mat, bool sync_to_rb)
{
    scale_mat = mat;
    transform = translation_mat * rotate_mat * scale_mat;

    if (rb && sync_to_rb)
    {
        rb->SetScaleMat(mat);
        rb->convex->UpdateWithModelMatrix(transform);
    }
}

//void Model::Update()
//{
//    if (rb && rb->convex) {
//        rb->convex->UpdateWithModelMatrix(transform);
//    }
//}

std::shared_ptr<Phy::RigidBody> Model::GetRB()
{
    return rb;
}

glm::mat4 Model::GetTranslationMat() const
{
    return translation_mat;
}

glm::mat4 Model::GetRotationMat() const
{
    return rotate_mat;
}

glm::mat4 Model::GetScaleMat() const
{
    return scale_mat;
}

//////////////////////////////////////////////////



